﻿using System;
using System.Diagnostics;
using System.IO;
using System.Xml.Serialization;
using SterlingLib;

namespace Algobox.Interop.SterlingTrader
{
    public class OrderManagement
    {
        private object _lockOrders = new object();
        private bool _isStarted = false;
        XmlSerializer _serialiserOrderUpdate = new XmlSerializer(typeof(SterlingLib.structSTIOrderUpdate));
        XmlSerializer _serialiserOrderConfirm= new XmlSerializer(typeof(SterlingLib.structSTIOrderConfirm));
        XmlSerializer _serialiserOrderReject = new XmlSerializer(typeof(SterlingLib.structSTIOrderReject));

        public virtual bool Start()
        {
            if (!_isStarted)
            {
                if (!SterlingWrapper.Start())
                    return false;
                try
                {
                    if (SterlingWrapper.STIOrder == null)
                    {
                        SterlingWrapper.STIOrder = new SterlingLib.STIOrder();
                    }
                    if (SterlingWrapper.STIOrderMaint == null)
                    {
                        SterlingWrapper.STIOrderMaint = new STIOrderMaint();
                    }
                    if (SterlingWrapper.STIEvents == null)
                    {
                        SterlingWrapper.STIEvents = new STIEvents();
                    }

                    SterlingWrapper.STIEvents.SetOrderEventsAsStructs(true);

                    SterlingWrapper.STIEvents.OnSTIOrderUpdateXML += new _ISTIEventsEvents_OnSTIOrderUpdateXMLEventHandler(OnSTIOrderUpdateXML);
                    SterlingWrapper.STIEvents.OnSTIOrderRejectXML += new _ISTIEventsEvents_OnSTIOrderRejectXMLEventHandler(OnSTIOrderRejectXML);
                    //SterlingWrapper.STIEvents.OnSTIOrderConfirmXML +=new _ISTIEventsEvents_OnSTIOrderConfirmXMLEventHandler(STIEvents_OnSTIOrderConfirmXML);

                    SterlingWrapper.OnSterlingShutdown += new SterlingWrapper.STIShutdown(OnSterlingShutdown);
                }
                catch
                {
                    return false;
                }
                _isStarted = true;
            }
            return true;
        }

        public virtual void Stop()
        {
            if (_isStarted)
            {
                _isStarted = false;
            }
        }

        void OnSTIOrderConfirmXML(ref string bstrOrder)
        {
            structSTIOrderConfirm order = (structSTIOrderConfirm)_serialiserOrderConfirm.Deserialize(new StringReader(bstrOrder));
            PostProcessOrder(ref order);
        }

        void OnSTIOrderUpdateXML(ref string bstrOrder)
        {
            structSTIOrderUpdate order = (structSTIOrderUpdate)_serialiserOrderUpdate.Deserialize(new StringReader(bstrOrder));
            PostProcessOrder(ref order);
        }

        void OnSTIOrderRejectXML(ref string bstrOrder)
        {
            structSTIOrderReject order = (structSTIOrderReject)_serialiserOrderReject.Deserialize(new StringReader(bstrOrder));
            PostProcessOrder(ref order);
        }

        void OnSterlingShutdown()
        {
            PostProcessSterlingShutdown();
        }

        public virtual void PostProcessOrder(ref structSTIOrderConfirm order)
        {
            Debug.WriteLine(String.Format("ORDER_CONFIRM {0} {1} {2} {3}", order.bstrClOrderId, order.nOrderRecordId, order.bstrAccount, order.bstrMsgConfirm));
        }

        public virtual void PostProcessOrder(ref structSTIOrderUpdate order)
        {
            Debug.WriteLine(String.Format("ORDER_UPDATE {0} {1} {2} {3} {4} {5} {6} {7} {8}@{9}", order.bstrClOrderId, order.nOrderRecordId, order.bstrAccount, order.bstrAction, order.bstrSymbol, order.bstrCurrency, order.bstrDestination, order.bstrSide, order.fAvgExecPrice, order.nQuantity));
        }

        public virtual void PostProcessOrder(ref structSTIOrderReject order)
        {
            Debug.WriteLine(String.Format("ORDER_REJECT {0} {1} {2} {3} {4} {5} {6}", order.bstrClOrderId, order.bstrAccount, order.bstrSymbol, order.bstrCurrency, order.bstrDestination, order.nRejectReason, order.bstrText));
        }

        public virtual void PostProcessSterlingShutdown()
        {
            Debug.WriteLine("SHUTDOWN " + DateTime.Now);
        }

        protected OrderResultCodes SubmitOrder(ref structSTIOrder order)
        {
            STIOrder STIOrder = new STIOrder();
            lock (_lockOrders)
            {
                return (OrderResultCodes)STIOrder.SubmitOrderStruct(ref order);
            }
        }

        protected OrderResultCodes ReplaceOrder(ref structSTIOrder order, int oldOrderRecordId, string oldClientOrderId)
        {
            STIOrder STIOrder = new STIOrder();
            lock (_lockOrders)
            {
                return (OrderResultCodes)STIOrder.ReplaceOrderStruct(ref order, oldOrderRecordId, oldClientOrderId);
            }
        }

        
        protected void CancelOrder(string account, int orderRecordId, string oldClientOrderId, string newClientOrderId)
        {
            STIOrderMaint STIOrderMaint = new STIOrderMaint();
            lock (_lockOrders)
            {
                STIOrderMaint.CancelOrder(account, orderRecordId, oldClientOrderId, newClientOrderId);
            }
        }

        protected void CancelOrder(ref structSTIOrder order)
        {
            STIOrder STIOrder = new STIOrder();
            lock (_lockOrders)
            {
                STIOrder.ClearOrderStruct(order);
            }
        }

        protected structSTIOrderUpdate GetOrderInfo(string clientOrderId)
        {
            STIOrderMaint STIOrderMaint = new STIOrderMaint();
            lock (_lockOrders)
            {
                return STIOrderMaint.GetOrderInfo(clientOrderId);
            }
        }

        protected enum OrderStatus
        {
            Unknown,
            PendingCancel,
            PendingReplace,
            DoneForDay,
            Calculated,
            Filled,
            Stopped,
            Suppended,
            Canceled,
            Expired,
            PartiallyFilled,
            Replaced,
            Rejected,
            New,
            PendingNew,
            AcceptedForBidding,
            Adjusted,
            Statused
        }

        protected enum PriceType
        {
            Market = 1,
            MarketOnClose = 2,
            MarketOrBetter = 3,
            MarketWithoutWaiting = 4,
            Limit = 5,
            LimitOnClose = 6,
            StopOrder = 7,
            StopLimitOrder = 8,
            LimitOrderBetter = 9,
            WithoutWaiting = 10,
            LimitWithoutWaiting = 11,
            NYSEBasisOrder = 12,
            CloseOrder = 13,
            PeggedOrder = 14,
            ServerSideStopOrder = 100,
            ServerSideStopLimitOrder = 101,
            TrailingStopOrder = 102
        }

        protected enum Side
        {
            Buy = 'B',
            BuyToCover = 'C',
            Sell = 'S',
            SellShort = 'T',
            BuyMinus = 'M',
            SellPlus = 'P',
            SellShortEx = 'E'
        }

        protected enum TIF
        {
            DAY = 'D', 
            GTC = 'G', 
            GTX = 'X', 
            FOK = 'F', 
            IOC = 'I',
            OPG = 'O', 
            EXT = 'E', 
            OS = '1', 
            AEX = 'A', 
            NOW = 'N'
        }

        protected enum Action
        {
            Add = 'A',
            Change = 'C',
            Delete = 'D',
            Status = 'S'
        }



        protected enum OrderResultCodes
        {
            NoError = 0,
            InvalidAccount = -1,
            InvalidSide = -2,
            InvalidQuantity = -3,
            InvaidSymbol = -4,
            InvalidPriceType = -5,
            InvalidTIF = -6,
            InvalidDestination = -7,
            ExposureLimitViolation = -8,
            NYSERulesViolation = -9,
            NYSE30SecondViolation = -10,
            DisableSelectNetShortSales = -11,
            LongSalePositionRulesViolation = -12,
            ShortSalePositionRulesViolation = -13,
            GTCOrdersNotEnabled = -14,
            ActiveXAPINotEnabled = -15,
            SterlingTraderProOffline = -16,
            SecurityNotMarkedAsLocated = -17,
            OrderSizeViolation = -18,
            PositionLimitViolation = -19,
            BuyingPowerLimitViolation = -20,
            PLControlViolation = -21,
            AccountNotEnabledForThisProduct = -22,
            TraderNotEnabledForFutures = -23,
            MinimumBalanceViolation = -24,
            TraderNotEnabledForOddLots = -25,
            OrderDollarLimitExceeded = -26,
            TraderNotEnabledForOptions = -27,
            SoftShareLimitExceeded = -28,
            LossFromMaxProfitControlLimitsViolation = -29,
            DeskQuantityEnforcementViolation = -30,
            AccountNoptEnabledForSellToOpen = -31,
            AccountAllowedToCloseOrCancelOnly = -32,
            TraderNotEnabledFroSecurityLocating = -33,
            OrderNotAbleToBeReplaced = -34,
            TraderNotEnabledForBuyToCover = -35,
            InvalidMaturityDate = -36,
            OnlyOneCancelOrReplaceAllowedPerOrderBySecond = -37,
            AccountMaximumPositionValueForSymbolExceeded = -38,
            SymbolViolatesAccountsMinMaxPriceSettings = -39
        }

        protected enum RejectReason
        {
            Unknown,
            UnknownPid,
            InvalidPassword,
            AccessDenied,
            NotFound,
            CannotRoute,
            PendingCancel,
            PendingReplace,
            OrderClosed,
            CannotCreate,
            DupeClientOrderId,
            NoSeqNumAvailable,
            InvalidAccount,
            InvalidDestination,
            Error,
            DupeSeqNum,
            NoChange,
            InvalidSeqNum,
            InvalidQty,
            TooLateToCancel,
            ShareLimit,
            DollarLimit,
            BuyingPower,
            TenSecRule,
            NotSupported,
            DupeAcct,
            InvalidGroupId,
            DupeStation,
            PosTradingLmt,
            TooLateToCancelMOC,
            HardToBorrow,
            Version,
            DupeLogin,
            InvalidSymbol,
            NxRules,
            BulletNotRequired,
            MOCMarketImbalance,
            Nx30SecRule,
            EasyToBorrowOnly,
            StaleOrder,
            Last
        }
    }
}
